package com.example.opengl.render.image

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.opengl.GLES11Ext
import android.opengl.GLES20
import android.opengl.GLES20.*
import android.opengl.GLUtils
import android.opengl.Matrix
import android.util.Log
import com.android.baselibrary.app.MainApplication
import com.example.opengl.R
import com.example.opengl.base.ShaderHelper
import com.example.opengl.base.TextResourceReader
import com.example.opengl.render.base.IDrawer
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import java.nio.ShortBuffer

/**
 * @author: Mr.You
 * @create: 2023-07-31 14:27
 * @description:
 **/
class ImageDrawer : IDrawer {
    companion object {
        const val TAG = "ImageDrawer"
    }

    private val vextexCoords = floatArrayOf(
        1f, 1f, 0f,
        -1f, 1f, 0f,
        -1f, -1f, 0f,
        1f, -1f, 0f

    )
    private val textureCoodrs = floatArrayOf(
        1f, 0f,
        0f, 0f,
        0f, 1f,
        1f, 1f
    )

    private var mVerTexShader = -1
    private var mTextureShader = -1

    private var mVerTexFloatBuffer: FloatBuffer? = null
    private var mTextureFloatBuffer: FloatBuffer? = null

    private var mShortBuffer: ShortBuffer? = null

    private var mTextureId = -1

    private var mProgram = -1

    private var mScreenWidth = 0

    private var mScreenHeight = 0

    private var mvpMatrixLocation = -1

    //变换矩阵
    private var mvpMatrix: FloatArray = FloatArray(16)

    private var mViewMatrix = FloatArray(16)
    private var mProjectMatrix = FloatArray(16)

    private var mBitmap: Bitmap? = null

    init {
        val byteBuffer = ByteBuffer.allocateDirect(vextexCoords.size * Float.SIZE_BYTES)
        byteBuffer.order(ByteOrder.nativeOrder())
        mVerTexFloatBuffer = byteBuffer.asFloatBuffer()
        mVerTexFloatBuffer?.put(vextexCoords)
        mVerTexFloatBuffer?.position(0)

        val tb = ByteBuffer.allocateDirect(textureCoodrs.size * Float.SIZE_BYTES)
        tb.order(ByteOrder.nativeOrder())
        mTextureFloatBuffer = tb.asFloatBuffer()
        mTextureFloatBuffer?.put(textureCoodrs)
        mTextureFloatBuffer?.position(0)



    }

    override fun draw() {
        //  if (mTextureId != -1) {

        onDraw()
        //  }

    }

    private fun initShader() {

        mVerTexShader =  ShaderHelper.compileVertexShader(TextResourceReader.readTextFileFormResource(resourceId = R.raw.image_vertex_shader))


        mTextureShader = ShaderHelper.compileFragmentShader(TextResourceReader.readTextFileFormResource(resourceId = R.raw.image_fragment_shader))

        mProgram = ShaderHelper.linkProgram(mVerTexShader,mTextureShader)
        glUseProgram(mProgram)

        mvpMatrixLocation = glGetUniformLocation(mProgram, "mvpMatrix")



        glDeleteShader(mTextureShader)
        glDeleteShader(mVerTexShader)

        mTextureId = loadTexture(R.drawable.image)
        Log.i(TAG, "initShader: mTextureId:$mTextureId")


    }



    private fun onDraw() {
        glClear(GL_COLOR_BUFFER_BIT)
        //设置变换矩阵
        glUniformMatrix4fv(mvpMatrixLocation, 1, false, mvpMatrix, 0)

        glEnableVertexAttribArray(0)
        glEnableVertexAttribArray(1)

        glVertexAttribPointer(0, 3, GL_FLOAT, false, 0, mVerTexFloatBuffer)
        glVertexAttribPointer(1, 2, GL_FLOAT, false, 0, mTextureFloatBuffer)

        glActiveTexture(GL_TEXTURE)

        glBindTexture(GL_TEXTURE_2D, mTextureId)

         glDrawArrays(GL_TRIANGLE_FAN, 0, 4)


        glDisableVertexAttribArray(0)
        glDisableVertexAttribArray(1)


    }

    override fun setTextureID(id: Int) {
        // mTextureId = id
    }

    override fun release() {

    }

    override fun setWorldSize(worldW: Int, worldH: Int) {
        mScreenWidth = worldW
        mScreenHeight = worldH
        glClearColor(0.1f, 0.2f, 0.3f, 0.4f)
        initShader()
        glViewport(0, 0, worldW, worldH)
        transform(worldW, worldH, mvpMatrix)


    }

    private var mWidthRatio = 1f
    private var mHeightRatio = 1f
    private fun transform(width: Int, height: Int, matrix: FloatArray) {

        val mVideoWidth = mBitmap!!.width
        val mVideoHeight = mBitmap!!.height
        val mWorldWidth = width
        val mWorldHeight = height
        // Log.i("TAGass", "transform: $mBitmap ,width:$widthBitmap , height:$heightBitmap")
        /* val mapRation = widthBitmap?.div((heightBitmap?.toFloat() ?: 1f))
         var ratio = width / height.toFloat()
         var w = 1.0f
         var h = 1.0f
         if (mapRation != null) {
             if (mapRation > ratio) {
                 h = mapRation / ratio
             } else {
                 w = ratio / mapRation
             }
         }
         Log.i("TAGass", "matrix: $matrix ,w:$w , h:$h")
         Matrix.orthoM(matrix, 0, -w, w, -h, h, -1f, 1f)*/



        if (mVideoWidth != -1 && mVideoHeight != -1 &&
            mWorldWidth != -1 && mWorldHeight != -1
        ) {
            // mMatrix = FloatArray(16)
            val prjMatrix = FloatArray(16)
            val originRatio = mVideoWidth / mVideoHeight.toFloat()
            val worldRatio = mWorldWidth / mWorldHeight.toFloat()
            if (mWorldWidth > mWorldHeight) {
                if (originRatio > worldRatio) {
                    mHeightRatio = originRatio / worldRatio
                    Matrix.orthoM(
                        prjMatrix, 0,
                        -mWidthRatio, mWidthRatio,
                        -mHeightRatio, mHeightRatio,
                        3f, 5f
                    )
                } else {// 原始比例小于窗口比例，缩放高度度会导致高度超出，因此，高度以窗口为准，缩放宽度
                    mWidthRatio = worldRatio / originRatio
                    Matrix.orthoM(
                        prjMatrix, 0,
                        -mWidthRatio, mWidthRatio,
                        -mHeightRatio, mHeightRatio,
                        3f, 5f
                    )
                }
            } else {
                if (originRatio > worldRatio) {
                    mHeightRatio = originRatio / worldRatio
                    Matrix.orthoM(
                        prjMatrix, 0,
                        -mWidthRatio, mWidthRatio,
                        -mHeightRatio, mHeightRatio,
                        3f, 5f
                    )
                } else {// 原始比例小于窗口比例，缩放高度会导致高度超出，因此，高度以窗口为准，缩放宽度
                    mWidthRatio = worldRatio / originRatio
                    Matrix.orthoM(
                        prjMatrix, 0,
                        -mWidthRatio, mWidthRatio,
                        -mHeightRatio, mHeightRatio,
                        3f, 5f
                    )
                }
            }


            //设置相机位置
            val viewMatrix = FloatArray(16)
            Matrix.setLookAtM(
                viewMatrix, 0,
                0f, 0f, 5.0f,
                0f, 0f, 0f,
                0f, 1.0f, 0f
            )
            //计算变换矩阵
            Matrix.multiplyMM(mvpMatrix, 0, prjMatrix, 0, viewMatrix, 0)
        }


    }

    private fun loadTexture(resourceId: Int): Int {
        val options = BitmapFactory.Options()
        options.inScaled = false
        mBitmap = BitmapFactory.decodeResource(MainApplication.mainApplication.resources, resourceId, options)

        val textureId = IntArray(1)
        glGenTextures(1, textureId, 0)

        //绑定纹理id
        glBindTexture(GL_TEXTURE_2D, textureId[0])


        Log.i(TAG, "loadTexture: bitmap:$mBitmap")


        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)

        //加载bitmap到纹理中
        GLUtils.texImage2D(GL_TEXTURE_2D, 0, mBitmap, 0)


        //生成mip贴图
        glGenerateMipmap(GL_TEXTURE_2D)




        //取消绑定纹理
        glBindTexture(GL_TEXTURE_2D, 0)

        return textureId[0]


    }


    override fun setVideoSize(videoW: Int, videoH: Int) {

    }
}